library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity uart_tx is
	generic(
		DBIT: integer:=8; -- # data bits
		SB_TICK: integer:=16 -- #ticks for stop bits
	);
	port(
		clk, reset: in std_logic;
		tx_start: in std_logic;
		s_tick: in std_logic;
		din: in std_logic_vector(7 downto 0);
		tx_done_tick: out std_logic;
		tx: out std_logic
	);
end uart_tx;

architecture arch of uart_tx is
	type state_type is (idle, start, data, stop);
	signal state_reg, state_next: state_type;
	signal s_reg, s_next: unsigned(3 downto 0);
	signal n_reg, n_next: unsigned(2 downto 0);
	signal b_reg, b_next: std_logic_vector(7 downto 0);
	signal tx_reg, tx_next: std_logic;
begin
	-- FSMD state & data registers
	process(clk, reset)
	begin
		if reset='1' then
			state_reg <= idle;
			s_reg <= ( others => '0');
			n_reg <= ( others => '0');
			b_reg <= ( others => '0');
			tx_reg <= '1';
		elsif (clk'event and clk='1') then
			state_reg <= state_next;
			s_reg <= s_next;
			n_reg <= n_next;
			b_reg <= b_next;
			tx_reg <= tx_next;
		end if;
	end process;
	-- next-state logic & data path functional units/routing
	process(state_reg, s_reg, n_reg, b_reg,  s_tick,
			tx_reg, tx_start, din)
	begin
		state_next <= state_reg;
		s_next <= s_reg;
		n_next <= n_reg;
		b_next <= b_reg;
		tx_next <= tx_reg;
		tx_done_tick <= '0';
		case state_reg is
		when idle =>
			tx_next <= '1';
			if tx_start='1' then
			state_next <= start;
			s_next <= (others => '0');
			b_next <= din;
		end if;
	when start =>
		tx_next <='0';
		if (s_tick = '1') then
			if s_reg = 15 then
				state_next <= data;
				s_next <= (others => '0');
				n_next <= (others => '0');
			else
				s_next <= s_reg + 1;
			end if;
		end if;
	when data =>
		tx_next <= b_reg(0);
		if (s_tick='1') then
			if s_reg=15 then
				s_next <= (others=>'0');
				b_next <= '0' & b_reg (7 downto 1);
				if n_reg =(DBIT-1) then
					state_next <= stop;
				else
					n_next <= n_reg + 1;
				end if;
			else
				s_next <= s_reg +1;
			end if;
		end if;
	when stop =>
		tx_next <= '1';
		if (s_tick='1') then
			if s_reg=(SB_TICK-1) then
				state_next <= idle;
				tx_done_tick <= '1';
				else
					s_next <= s_reg + 1;
				end if;
			end if;
		end case;
	end process;
	tx <= tx_reg;
end arch;
